package fr.uhp.mpr.bayesnetwork;
import java.util.ArrayList;

import fr.uhp.mpr.data.DataExplore;
import fr.uhp.mpr.data.DataMeter;
import fr.uhp.mpr.data.Intervalle;

/**
 * Classe analysant les donnees recueillies afin de
 * determiner les dependances entre elles, et ainsi
 * permettre une description du reseau bayesien.
 */
public class CheckDependancies {

	private ArrayList<ArrayList<Double>> liste = DataExplore.getInstance().getListe();


	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "CheckDependancies [liste=" + liste + "]";
	}
	
	/**
	 * Trouve les dependances entre variables et met a jour le reseau.
	 */
	public void findCorrelation() {
		System.out.println("==================================\nCorrelations lineaires\n==================================\n");
		for(int i = 0; i < liste.size()-1; i++){
			for(int j = i+1; j < liste.size()-1; j++){
					double ind = getPearsonCorrelation(liste.get(i), liste.get(j));
					if(ind >= 0.75)
						System.out.println(
								"- "+DataMeter.iname.values()[i]+" et "
								+DataMeter.iname.values()[j]+" "
								+"("+ind+")"
						);
				}
			}
	}
	
	/**
	 * http://snippets.dzone.com/posts/show/4910
	 * @param scores1
	 * @param scores2
	 * @return valeur entre -1 et 1. Plus la valeur est proche des extrema, plus la correlationest forte.
	 */
	public static double getPearsonCorrelation(ArrayList<Double> scores1, ArrayList<Double> scores2){
        double result = 0;
        double sum_sq_x = 0, sum_sq_y = 0;
        double sum_coproduct = 0;
        double mean_x = scores1.get(0), mean_y = scores2.get(0);
        
        for(int i = 2; i < scores1.size()+1; i++){
            double sweep = Double.valueOf(i-1) / i;
            double delta_x = scores1.get(i-1) - mean_x;
            double delta_y = scores2.get(i-1) - mean_y;
            sum_sq_x += delta_x * delta_x * sweep;
            sum_sq_y += delta_y * delta_y * sweep;
            sum_coproduct += delta_x * delta_y * sweep;
            mean_x += delta_x / i;
            mean_y += delta_y / i;
        }
        
        double pop_sd_x = (double) Math.sqrt(sum_sq_x / scores1.size());
        double pop_sd_y = (double) Math.sqrt(sum_sq_y / scores1.size());
        double cov_x_y = sum_coproduct / scores1.size();
        result = cov_x_y / (pop_sd_x * pop_sd_y);
        
        return Math.abs(Math.round(result * 100.0) / 100.0);
    }
	
	public void findDependancies(){
		System.out.println("\n==================================\nIndependance probabiliste\n==================================\n");
		
		ArrayList<String> independances = new ArrayList<String>();
		int size = DataMeter.iname.values().length;

		for(int l = 0; l < size; l++){
			for(int m = 0; m < size; m++){
				if(l!=m)
					independances = check(
							DataMeter.iname.values()[l].toString(),
							DataMeter.iname.values()[m].toString(),
							DataExplore.getData(l),
							DataExplore.getData(m),
							DataMeter.getIntervalle(l),
							DataMeter.getIntervalle(m),
							independances);
			}
		}
		
		System.out.println("\nRESUME :");
		for(String s : independances){
			System.out.println(s);
		}	
	}
	
	public ArrayList<String> check(String nameVar1,String nameVar2,
			ArrayList<Double> arrayList, ArrayList<Double> arrayList2,
			Intervalle[] interVar1, Intervalle[] interVar2,
			ArrayList<String> ind){
		
		double[] counter1 = new double[interVar1.length];
		double[] counter2 = new double[interVar2.length];
		double[][] counter2D = new double[interVar1.length][interVar2.length];
		
		for(int i = 0;i<arrayList.size();i++){
			int ind1 = -1;
			int ind2 = -1;
		
			for(int v1 =0;v1<interVar1.length;v1++){
				if(interVar1[v1].contains(arrayList.get(i))){
					ind1 = v1;
					break;
				}
			}
			
			for(int v2 =0;v2<interVar2.length;v2++){
				if(interVar2[v2].contains(arrayList2.get(i))){
					ind2 = v2;
					break;
				}	
			}

			counter1[ind1]++;
			counter2[ind2]++;
			counter2D[ind1][ind2]++;
		}
		
		for(int x = 0;x<counter2.length;x++)
			counter2[x] = counter2[x]/arrayList2.size();
		
		for(int y = 0;y<counter1.length;y++)
			counter1[y] = counter1[y]/arrayList.size(); 
		
		ArrayList<String> independances = ind;
		
		final double ALPHA = 0.05;
		
		for(int l = 0;l<counter2.length;l++){
			for(int m = 0;m<counter1.length;m++){
				counter2D[m][l] = counter2D[m][l]/(arrayList.size());
		
				if(!almostEqu(counter2D[m][l], (counter1[m]*counter2[l]), ALPHA)){
					System.out.println(
							"P("+nameVar1+"="+arrayList.get(l).toString()+","
							+nameVar2+"="+arrayList2.get(m).toString()+")="
							+counter2D[m][l]+"\n"
							+"P("+nameVar1+"="+arrayList.get(l).toString()+")P("
							+nameVar2+"="+arrayList2.get(m).toString()+")="
							+(counter1[m]*counter2[l])+"\n"
					);
				
					if(! (independances.contains(nameVar2+" et "+nameVar1) || independances.contains(nameVar1+" et "+nameVar2)))
						independances.add(nameVar1+" et "+nameVar2);
				}
			}
		}
		
		return independances;
	}
	
	private boolean almostEqu(double d1, double d2, double alpha){
		return  Math.abs(d1-d2) < alpha;
	}
	
	public static void main(String[] args) {
		CheckDependancies cd = new CheckDependancies();
		DataExplore.getInstance();
		cd.findCorrelation();
		cd.findDependancies();
	}
}
